﻿#include"stdafx.h"
#include"index_manage.h"
#include"util.h"
index_manage::index_manage()
{
}

index_manage::~index_manage()
{

}

bool index_manage::IsInMem(string auth)
{
	vector <string>::iterator iter = indexNames.find(auth);
	if (indexNames.end() != iter) {
		return true;
	}
	return false;
}

void index_manage::findInt(vector<int>&vec, struct_where index, string auth) {
	int value = stoi(index.value);
	MIndexInt indexInt;
	//LRU算法
	for (list<MIndexInt>::iterator it = containerInt.begin(); it != containerInt.end(); it++) {
		if ((*it).Identifier == auth) {
			indexInt = *it;
			containerInt.erase(it);
			containerInt.push_back(indexInt);
			break;
		}
	}
	multimap<int, int>::iterator p_map;
	pair<multimap<int, int>::iterator, multimap<int, int>::iterator> ret;
	ret = indexInt.record.equal_range(value);
	if (index.operater == "=") {
		for (p_map = ret.first; p_map != ret.second; ++p_map)
			vec.push_back((*p_map).second);
	}
	else if (index.operater == ">") {
		for (p_map = ret.first; p_map != indexInt.record.end(); ++p_map) {
			if ((*p_map).first == value)
				continue;
			vec.push_back((*p_map).second);
		}
	}
	else if (index.operater == "<") {
		for (p_map = ret.first; p_map != indexInt.record.begin(); --p_map)
			vec.push_back((*p_map).second);
		vec.push_back((*(indexInt.record.begin())).second);
	}
}

void index_manage::findDouble(vector<int>&vec, struct_where index, string auth)
{
	double value = stod(index.value);
	//LRU算法
	MIndexDouble IndexDouble;
	for (list<MIndexDouble>::iterator it = containerDouble.begin(); it != containerDouble.end(); it++) {
		if ((*it).Identifier == auth) {
			IndexDouble = *it;
			containerDouble.erase(it);
			containerDouble.push_back(IndexDouble);
			break;
		}
	}
	multimap<double, int>::iterator p_map;
	pair<multimap<double, int>::iterator, multimap<double, int>::iterator> ret;
	ret = IndexDouble.record.equal_range(value);
	if (index.operater == "=") {
		for (p_map = ret.first; p_map != ret.second; ++p_map)
			vec.push_back((*p_map).second);
	}
	else if (index.operater == ">") {
		for (p_map = ret.first; p_map != IndexDouble.record.end(); ++p_map)
			vec.push_back((*p_map).second);
	}
	else if (index.operater == "<") {
		for (p_map = ret.first; p_map != IndexDouble.record.begin(); --p_map)
			vec.push_back((*p_map).second);
		vec.push_back((*(IndexDouble.record.begin())).second);
	}
}

void index_manage::findChar(vector<int>& vec, struct_where index, string auth)
{
	string value = index.value;
	//LRU
	MIndexChar IndexChar;
	for (list<MIndexChar>::iterator it = containerChar.begin(); it != containerChar.end(); it++) {
		if ((*it).Identifier == auth) {
			IndexChar = *it;
			containerChar.erase(it);
			containerChar.push_back(IndexChar);
			break;
		}
	}
	multimap<string, int>::iterator p_map;
	pair<multimap<string, int>::iterator, multimap<string, int>::iterator> ret;
	ret = IndexChar.record.equal_range(value);
	if (index.operater == "=") {
		for (p_map = ret.first; p_map != ret.second; ++p_map)
			vec.push_back((*p_map).second);
	}
	else if (index.operater == ">") {
		for (p_map = ret.first; p_map != IndexChar.record.end(); ++p_map)
			vec.push_back((*p_map).second);
	}
	else if (index.operater == "<") {
		for (p_map = ret.first; p_map != IndexChar.record.begin(); --p_map)
			vec.push_back((*p_map).second);
		vec.push_back((*(IndexChar.record.begin())).second);
	}
}

void index_manage::findResult(vector<int>& vec, struct_where index, string auth)
{
	if (index.type == "1") {
		findInt(vec, index, auth);
	}
	else if (index.type == "3") {
		findDouble(vec, index, auth);
	}
	else if (index.type == "4") {
		findChar(vec, index, auth);
	}
}

//从内存中清理某个索引
void index_manage::Erase(string auth)
{
	set<string>::iterator iter = indexNames.find(auth);
	indexNames.erase(iter);
	for (list<MIndexInt>::iterator it = containerInt.begin(); it != containerInt.end(); it++) {
		if ((*it).Identifier == auth) {
			containerInt.erase(it);
			return;
		}
	}

	for (list<MIndexDouble>::iterator it = containerDouble.begin(); it != containerDouble.end(); it++) {
		if ((*it).Identifier == auth) {
			containerDouble.erase(it);
			return;
		}
	}

	for (list<MIndexChar>::iterator it = containerChar.begin(); it != containerChar.end(); it++) {
		if ((*it).Identifier == auth) {
			containerChar.erase(it);
			return;
		}
	}
}

//读入内存
void index_manage::push_to_mem(string path, struct_where index, string auth)
{
	indexNames.insert(auth);
	CFile file;
	CString Path;
	Path = path.c_str();
	file.Open(Path, CFile::modeRead | CFile::typeBinary, NULL);
	file.SeekToBegin();
	if (index.type == "1") {
		MIndexInt IndexInt;
		IndexInt.Identifier = auth;
		IndexInt.path = path;
		//LRU
		if (containerInt.size() >= CacheSize) {
			set<string>::iterator iter = indexNames.find(containerInt.front().Identifier);
			indexNames.erase(iter);
			containerInt.pop_front();
		}
		int key = 0, pos = 0;
		while (file.Read(&key, 4) != 0) {
			file.Read(&pos, 4);
			IndexInt.record.insert(make_pair(key, pos));
		}
		containerInt.push_back(IndexInt);
	}
	else if (index.type == "3") {
		MIndexDouble IndexDouble;
		IndexDouble.Identifier = auth;
		IndexDouble.path = path;
		//LRU
		if (containerDouble.size() >= CacheSize) {
			set<string>::iterator iter = indexNames.find(containerDouble.front().Identifier);
			indexNames.erase(iter);
			containerDouble.pop_front();
		}
		double key = 0;
		int pos = 0;
		while (file.Read(&key, 8) != 0) {
			file.Read(&pos, 4);
			IndexDouble.record.insert(make_pair(key, pos));
		}
		containerDouble.push_back(IndexDouble);
	}
	else if (index.type == "4") {
		MIndexChar IndexChar;
		IndexChar.Identifier = auth;
		IndexChar.path = path;
		//LRU
		if (containerChar.size() >= CacheSize) {
			set<string>::iterator iter = indexNames.find(containerChar.front().Identifier);
			indexNames.erase(iter);
			containerChar.pop_front();
		}
		char  key[256] = { 0 };
		int pos = 0;
		while (file.Read(key, index.size) != 0) {
			file.Read(&pos, 4);
			string str_key = key;
			IndexChar.record.insert(make_pair(str_key, pos));
		}
		containerChar.push_back(IndexChar);
	}
	file.Close();

}

//生成新的索引
void index_manage::ReProduceIndex(string path, string column,string auth, int pos, int lenth, int size)
{
	CFile file;
	string tpath = path + ".trd";
	CString cpath; cpath = tpath.c_str();
	CFile index_file;
	CString indexPath;
	path += "_" + column;
	indexPath = path.c_str();

	file.Open(cpath, CFile::modeReadWrite | CFile::typeBinary, NULL);
	index_file.Open(indexPath + L".tid.temp", CFile::modeCreate);
	index_file.Close();
	index_file.Open(indexPath + L".tid.temp", CFile::modeReadWrite | CFile::typeBinary, NULL);
	file.Seek(pos, file.begin);
	char*	temp_arr = new char[size + 1];
	memset(temp_arr, 0, size + 1);
	int count = 0;
	while (file.Read(temp_arr, size) != 0) {
		int position = 0;
		position = count*lenth;
		index_file.Write(temp_arr, size);
		index_file.Write(&position, 4);
		memset(temp_arr, 0, size + 1);
		count++;
		file.Seek(lenth - size, file.current);
	}
	file.Close();
	index_file.Close();
	delete temp_arr;
	string tempPath = CStringTostring(indexPath + L".tid");
	if (FileExist(tempPath.c_str()))
		file.Remove(indexPath + L".tid");
	file.Rename(indexPath + L".tid.temp", indexPath + L".tid");
	if (IsInMem(auth)) {
		Erase(auth);
	}
}

vector<int> index_manage::update(string path, string auth, struct_where index)
{
	return vector<int>();
}

vector<int> index_manage::select(string path, string auth, struct_where index)
{
	vector<int>result;
	if (IsInMem(auth)) {
		//索引在内存中
		findResult(result, index, auth);
	}
	else {
		push_to_mem(path, index, auth);
		findResult(result, index, auth);
		//TODO 读入内存 返回索引
	}
	return result;
}

void index_manage::insert(string path, string auth, indexInt index)
{
	if (IsInMem(auth)) {
		//改变内存中的索引
		for (list<MIndexInt>::iterator it = containerInt.begin(); it != containerInt.end(); it++) {
			if ((*it).Identifier == auth) {
				(*it).record.insert(make_pair(index.key, index.pos));
				break;
			}
		}
	}
	//写入文件
	CFile file;
	CString cspath; cspath = path.c_str();
	file.Open(cspath, CFile::modeWrite | CFile::typeBinary, NULL);
	file.SeekToEnd();
	file.Write(&index.key, 4);
	file.Write(&index.pos, 4);
	file.Close();
}

void index_manage::insert(string path, string auth, indexDouble index)
{
	if (IsInMem(auth)) {
		//改变内存中的索引
		for (list<MIndexDouble>::iterator it = containerDouble.begin(); it != containerDouble.end(); it++) {
			if ((*it).Identifier == auth) {
				(*it).record.insert(make_pair(index.key, index.pos));
				break;
			}
		}
	}
	//写入文件
	CFile file;
	CString cspath; cspath = path.c_str();
	file.Open(cspath, CFile::modeWrite | CFile::typeBinary, NULL);
	file.SeekToEnd();
	file.Write(&index.key, 8);
	file.Write(&index.pos, 4);
	file.Close();
}

void index_manage::insert(string path, string auth, indexChar index)
{
	if (IsInMem(auth)) {
		//改变内存中的索引
		for (list<MIndexChar>::iterator it = containerChar.begin(); it != containerChar.end(); it++) {
			if ((*it).Identifier == auth) {
				(*it).record.insert(make_pair(index.key, index.pos));
				break;
			}
		}
	}
	//写入文件
	CFile file;
	CString cspath; cspath = path.c_str();
	file.Open(cspath, CFile::modeWrite | CFile::typeBinary, NULL);
	file.SeekToEnd();
	file.Write(index.key, 256);
	file.Write(&index.pos, 4);
	file.Close();

}